package com.biqee.service.juhuasuan.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.biqee.exception.AccessBlockException;
import com.biqee.exception.BusinessUnCheckedException;
import com.biqee.exception.ErrorCode;
import com.biqee.model.JuHuaSuanItemOfPage;
import com.biqee.model.JuHuaSuanItemOfPage.JuHuaSuanItemStatus;
import com.biqee.model.TaobaoParseReulst;
import com.biqee.model.db.BqQueryRelation;
import com.biqee.model.db.BqTuan;
import com.biqee.model.db.TbItem;
import com.biqee.model.db.TbJuItem;
import com.biqee.service.bq.BqQueryRelationService;
import com.biqee.service.bq.BqTuanService;
import com.biqee.service.bq.EstimateService;
import com.biqee.service.crawler.PageFetcher;
import com.biqee.service.juhuasuan.ItemListParser;
import com.biqee.service.juhuasuan.ItemParser;
import com.biqee.service.juhuasuan.JuHuaSuanParseService;
import com.biqee.service.tb.TaobaoParseService;
import com.biqee.service.tb.TbItemService;
import com.biqee.service.tb.TbJuItemService;
import com.biqee.util.BqTuanUtil;
import com.biqee.util.StringUtil;
import com.biqee.util.TbJuItemUtil;
import com.biqee.util.UrlUtil;

public class JuHuaSuanParseServiceImpl implements JuHuaSuanParseService {
	
	private static final Logger logger = Logger.getLogger(JuHuaSuanParseServiceImpl.class);
	
	private static final String BASE_URL = "http://ju.taobao.com/tg/today_items.htm?page=";

	private static final long SLEEP_INTERVAL = 2000;
	
	@Override
	public void parseTodayData() {
		List<JuHuaSuanItemOfPage> itemBaseInfoList = getAllBaseInfo();
		parseBaseInfoList(itemBaseInfoList);
		estimateService.estimateAll();
	}
	
	@Override
	public void parseStatusByItemId(String itemId) {
		logger.info("parse status of item: " + itemId);
		String url = "http://ju.taobao.com/tg/home.htm?itemId=" + itemId;
		try {
			String htmlString = pageFetcher.getAsStringWithSpiderHeader(url, null);
			JuHuaSuanItemStatus status = itemParser.getJuHuaSuanItemStatus(htmlString, itemId);
			logger.info("status of item is: " + status.getStatus() + ", itemId: " + itemId);
			if(status != null) {
				if(status == JuHuaSuanItemStatus.SOLD_OUT || status == JuHuaSuanItemStatus.TIME_OUT) {
					BqTuan bqTuan = bqTuanService.readBySiteItem(BqTuan.SITE_TAOBAO, itemId);
					bqTuan.setIsExpire();
					bqTuanService.update(bqTuan);
				}
			}
		} catch (AccessBlockException abe) {
			logger.error("taobao block us. itemId: " + itemId);
			throw abe;
		} catch (Exception ex) {
			logger.error("parse error. itemId: " + itemId, ex);
		}
	}
	
	@Override
	public boolean parseByUrl(String url) {
		String itemId = UrlUtil.getParam(url, "itemId");
		if(itemId == null) {
			logger.error("bad url: " + url);
			throw new BusinessUnCheckedException(ErrorCode.JUHUASUAN_URL_ERROR);
		}
	
		return parseByUrl(url, false);
	}
	
	public boolean parseByUrl(String url, boolean mandatory) {
		String itemId = UrlUtil.getParam(url, "itemId");
		JuHuaSuanItemOfPage itemBaseInfo = new JuHuaSuanItemOfPage();
		itemBaseInfo.setItemId(itemId);
		itemBaseInfo.setDetailUrl(url);
		return parse(itemBaseInfo, mandatory);
	}
	
	private void parseBaseInfoList(List<JuHuaSuanItemOfPage> itemBaseInfoList) {
		for(JuHuaSuanItemOfPage itemBaseInfo : itemBaseInfoList) {
			try {
				parse(itemBaseInfo, false);
			} catch(AccessBlockException abe) {
				logger.error("taobao block us!");
			} catch (Exception ex) {
				logger.error("parse failed, itemId: " + itemBaseInfo.getItemId());
			}
			
			try {
				Thread.sleep(SLEEP_INTERVAL);
			} catch (InterruptedException e) {
				logger.error("thread interupted");
				return;
			}
		}
	}
	
	/**
	 * @param mandatory 是否强制解析，如果本参数为true，则不考虑是否已经解析过，总要进行解析，如果本参数为false，则如果已经解析过则不会继续解析，返回false
	 */
	private boolean parse(JuHuaSuanItemOfPage itemBaseInfo, boolean mandatory) {
		String itemId = itemBaseInfo.getItemId();
		TaobaoParseReulst result = taobaoParseService.parse(itemId);
		if (result == null || result.getTbItem() == null
				|| result.getTbShop() == null) {
			logger.error("parse item error, itemId: " + itemId);
			return false ;
		}
		logger.info("parsing itemId: " + itemId);
		
		TbJuItem tbJuItemInDB = tbJuItemService.readWithJuItemId(itemId);
		
		if(!mandatory) {
			boolean needParse = isNeedParse(tbJuItemInDB);
			if(!needParse) {
				logger.info("this item has been parsed. so skip it. itemId: " + tbJuItemInDB.getId());
				return false;
			}		
		}
		
		try {
			String jhsItemUrl = itemBaseInfo.getDetailUrl();
			String htmlStr = pageFetcher.getAsStringWithSpiderHeader(jhsItemUrl, null);
			itemParser.fillItemInfo(htmlStr, itemBaseInfo);
			
			JuHuaSuanItemStatus status = itemBaseInfo.getStatus();
			TbJuItem destItem = TbJuItemUtil.createTbJuItem(itemBaseInfo);
			if(destItem != null) {
				saveTbJuItem(tbJuItemInDB, destItem);
				processAfterSave(destItem, status, jhsItemUrl);
			}
		} catch (Exception ex) {
			logger.error("parse error. itemId: " + itemId, ex);
			return false;
		}
		
		return true;
	}

	private void saveTbJuItem(TbJuItem tbJuItemInDB, TbJuItem destItem) {
		if(tbJuItemInDB == null) {
			tbJuItemInDB = tbJuItemService.readWithJuItemId(destItem.getItemId());
			if(tbJuItemInDB == null) {
				tbJuItemService.create(destItem);
				return;
			}
		}

		destItem.setId(tbJuItemInDB.getId());
		tbJuItemService.update(destItem);
	}
	
	private int saveBqTuan(BqTuan toSave) {
		return bqTuanService.save(toSave);
	}
	
	private void saveBqQueryRelation(String itemId, int bqTuanId) {
		TbItem tbItem = tbItemService.getByTbItemId(itemId);
		if(tbItem != null) {
			Integer tbItemId = bqQueryRelationService.getTbItemId(bqTuanId);
			if(tbItemId != null) {
				if(!tbItemId.equals(tbItem.getId())) {
					logger.error("ref_id conflict! id in db: " + tbItemId + ", expected: " + tbItem.getId());
				}
			} else {
				BqQueryRelation bqQueryRelation = new BqQueryRelation();
				bqQueryRelation.setTuanId(bqTuanId);
				bqQueryRelation.setQueryId(-1);
				bqQueryRelation.setRank(-1);					
				bqQueryRelation.setRefId(tbItem.getId());
				bqQueryRelationService.save(bqQueryRelation);	
			}	
		}
	}
	
	private void processAfterSave(TbJuItem destItem, JuHuaSuanItemStatus status, String joinUrl) {
		logger.info("itemId: " + destItem.getItemId() +
				", status: " + status.getStatus() +
				", joinUrl: " + joinUrl);
		BqTuan toSave = BqTuanUtil.createBqTuan(destItem);
		toSave.setJoinUrl(joinUrl);
		if(status == JuHuaSuanItemStatus.TIME_OUT || status == JuHuaSuanItemStatus.SOLD_OUT) {
			toSave.setIsExpire();
		}
		
		int bqTuanId = saveBqTuan(toSave);
		toSave.setId(bqTuanId);
		
		String itemId = destItem.getItemId();
		saveBqQueryRelation(itemId, bqTuanId);	
	}
	
	private boolean isNeedParse(TbJuItem itemInDB) {
		if(itemInDB == null) {
			return true;
		} else {
			String juPrice = itemInDB.getJuPrice();
			return StringUtil.isBlank(juPrice);
		}
	}
	
	private List<JuHuaSuanItemOfPage> getAllBaseInfo() {
		List<JuHuaSuanItemOfPage> itemList = new ArrayList<JuHuaSuanItemOfPage>();
		
		String htmlStr = pageFetcher.getAsStringWithSpiderHeader(BASE_URL + 1, null);

		int pageNumber = itemListParser.getMaxPageNumber(htmlStr);
		if(pageNumber == 0) {
			logger.error("pageNumber is 0, maybe something is wrong, please check!");
			return itemList;
		}
		
		// parse page 1
		List<JuHuaSuanItemOfPage> resultList = itemListParser.parseAllItems(htmlStr);		
		itemList.addAll(resultList);
		
		// parse page 2 to max-page-number
		for(int i = 2; i <= pageNumber; i++) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				return itemList;
			}
			
			htmlStr = pageFetcher.getAsStringWithSpiderHeader(BASE_URL + i, null);
			List<JuHuaSuanItemOfPage> tempList = itemListParser.parseAllItems(htmlStr);
			itemList.addAll(tempList);
		}
		
		return itemList;
	}

	private PageFetcher pageFetcher;
	
	public void setPageFetcher(PageFetcher pageFetcher) {
		this.pageFetcher = pageFetcher;
	}
	
	private ItemListParser itemListParser;

	public void setItemListParser(ItemListParser itemListParser) {
		this.itemListParser = itemListParser;
	}

	private ItemParser itemParser;

	public void setItemParser(ItemParser itemParser) {
		this.itemParser = itemParser;
	}

	private TbJuItemService tbJuItemService;

	public void setTbJuItemService(TbJuItemService tbJuItemService) {
		this.tbJuItemService = tbJuItemService;
	}

	private BqTuanService bqTuanService;

	public void setBqTuanService(BqTuanService bqTuanService) {
		this.bqTuanService = bqTuanService;
	}

	private BqQueryRelationService bqQueryRelationService;

	public void setBqQueryRelationService(
			BqQueryRelationService bqQueryRelationService) {
		this.bqQueryRelationService = bqQueryRelationService;
	}
	
	private TaobaoParseService taobaoParseService;

	public void setTaobaoParseService(TaobaoParseService taobaoParseService) {
		this.taobaoParseService = taobaoParseService;
	}
	
	private TbItemService tbItemService;

	public void setTbItemService(TbItemService tbItemService) {
		this.tbItemService = tbItemService;
	}
	
	private EstimateService estimateService;

	public void setEstimateService(EstimateService estimateService) {
		this.estimateService = estimateService;
	}
	
	
}
